home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / qe4 / entity.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-18  |  10.0 KB  |  517 lines

  1. #include "qe3.h"
  2.  
  3. char     *ValueForKey (entity_t *ent, char *key)
  4. {
  5.     epair_t    *ep;
  6.     
  7.     for (ep=ent->epairs ; ep ; ep=ep->next)
  8.         if (!strcmp (ep->key, key) )
  9.             return ep->value;
  10.     return "";
  11. }
  12.  
  13. void     SetKeyValue (entity_t *ent, char *key, char *value)
  14. {
  15.     epair_t    *ep;
  16.  
  17.     if (ent == NULL)
  18.         return;
  19.  
  20.     if (!key || !key[0])
  21.         return;
  22.  
  23.     for (ep=ent->epairs ; ep ; ep=ep->next)
  24.         if (!strcmp (ep->key, key) )
  25.         {
  26.             free (ep->value);
  27.             ep->value = qmalloc(strlen(value)+1);
  28.             strcpy (ep->value, value);
  29.             return;
  30.         }
  31.     ep = qmalloc (sizeof(*ep));
  32.     ep->next = ent->epairs;
  33.     ent->epairs = ep;
  34.     ep->key = qmalloc(strlen(key)+1);
  35.     strcpy (ep->key, key);
  36.     ep->value = qmalloc(strlen(value)+1);
  37.     strcpy (ep->value, value);
  38. }
  39.  
  40. void     DeleteKey (entity_t *ent, char *key)
  41. {
  42.     epair_t    **ep, *next;
  43.     
  44.     ep = &ent->epairs;
  45.     while (*ep)
  46.     {
  47.         next = *ep;
  48.         if ( !strcmp (next->key, key) )
  49.         {
  50.             *ep = next->next;
  51.             free(next->key);
  52.             free(next->value);
  53.             free(next);
  54.             return;
  55.         }
  56.         ep = &next->next;
  57.     }
  58. }
  59.  
  60. float    FloatForKey (entity_t *ent, char *key)
  61. {
  62.     char    *k;
  63.     
  64.     k = ValueForKey (ent, key);
  65.     return atof(k);
  66. }
  67.  
  68. int IntForKey (entity_t *ent, char *key)
  69. {
  70.     char    *k;
  71.     
  72.     k = ValueForKey (ent, key);
  73.     return atoi(k);
  74. }
  75.  
  76. void     GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
  77. {
  78.     char    *k;
  79.     
  80.     k = ValueForKey (ent, key);
  81.     sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
  82. }
  83.  
  84.  
  85. /*
  86. ===============
  87. Entity_Free
  88.  
  89. Frees the entity and any brushes is has.
  90. The entity is removed from the global entities list.
  91. ===============
  92. */
  93. void Entity_Free (entity_t *e)
  94. {
  95.     epair_t    *ep, *next;
  96.  
  97.     while (e->brushes.onext != &e->brushes)
  98.         Brush_Free (e->brushes.onext);
  99.  
  100.     if (e->next)
  101.     {
  102.         e->next->prev = e->prev;
  103.         e->prev->next = e->next;
  104.     }
  105.  
  106.     for (ep = e->epairs ; ep ; ep=next)
  107.     {
  108.         next = ep->next;
  109.         free (ep);
  110.     }
  111.     free (e);
  112. }
  113.  
  114. /*
  115. =================
  116. ParseEpair
  117. =================
  118. */
  119. epair_t *ParseEpair (void)
  120. {
  121.     epair_t    *e;
  122.     
  123.     e = qmalloc (sizeof(*e));
  124.     
  125.     e->key = qmalloc(strlen(token)+1);
  126.     strcpy (e->key, token);
  127.  
  128.     GetToken (false);
  129.     e->value = qmalloc(strlen(token)+1);
  130.     strcpy (e->value, token);
  131.  
  132.     return e;
  133. }
  134.  
  135. /*
  136. ================
  137. Entity_Parse
  138.  
  139. If onlypairs is set, the classname info will not
  140. be looked up, and the entity will not be added
  141. to the global list.  Used for parsing the project.
  142. ================
  143. */
  144. entity_t    *Entity_Parse (qboolean onlypairs)
  145. {
  146.     entity_t    *ent;
  147.     eclass_t    *e;
  148.     brush_t        *b;
  149.     vec3_t        mins, maxs;
  150.     epair_t        *ep;
  151.     qboolean    has_brushes;
  152.  
  153.     if (!GetToken (true))
  154.         return NULL;
  155.  
  156.     if (strcmp (token, "{") )
  157.         Error ("ParseEntity: { not found");
  158.     
  159.     ent = qmalloc (sizeof(*ent));
  160.     ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
  161.  
  162.     do
  163.     {
  164.         if (!GetToken (true))
  165.             Error ("ParseEntity: EOF without closing brace");
  166.         if (!strcmp (token, "}") )
  167.             break;
  168.         if (!strcmp (token, "{") )
  169.         {
  170.             b = Brush_Parse ();
  171.             b->owner = ent;
  172.  
  173.             // add to the end of the entity chain
  174.             b->onext = &ent->brushes;
  175.             b->oprev = ent->brushes.oprev;
  176.             ent->brushes.oprev->onext = b;
  177.             ent->brushes.oprev = b;
  178.         }
  179.         else
  180.         {
  181.             ep = ParseEpair ();
  182.             ep->next = ent->epairs;
  183.             ent->epairs = ep;
  184.         }
  185.     } while (1);
  186.  
  187.     if (onlypairs)
  188.         return ent;
  189.  
  190.     if (ent->brushes.onext == &ent->brushes)
  191.         has_brushes = false;
  192.     else
  193.         has_brushes = true;
  194.  
  195.     GetVectorForKey (ent, "origin", ent->origin);
  196.  
  197.     e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
  198.     ent->eclass = e;
  199.     if (e->fixedsize)
  200.     {    // fixed size entity
  201.         if (ent->brushes.onext != &ent->brushes)
  202.         {
  203.             printf ("Warning: Fixed size entity with brushes\n");
  204. #if 0
  205.             while (ent->brushes.onext != &ent->brushes)
  206.             {    // FIXME: this will free the entity and crash!
  207.                 Brush_Free (b);
  208.             }
  209. #endif
  210. ent->brushes.next = ent->brushes.prev = &ent->brushes;
  211.         }
  212.         // create a custom brush
  213.         VectorAdd (e->mins, ent->origin, mins);
  214.         VectorAdd (e->maxs, ent->origin, maxs);
  215.         b = Brush_Create (mins, maxs, &e->texdef);
  216.         b->owner = ent;
  217.  
  218.         b->onext = ent->brushes.onext;
  219.         b->oprev = &ent->brushes;
  220.         ent->brushes.onext->oprev = b;
  221.         ent->brushes.onext = b;
  222.     }
  223.     else
  224.     {    // brush entity
  225.         if (ent->brushes.next == &ent->brushes)
  226.             printf ("Warning: Brush entity with no brushes\n");
  227.     }
  228.  
  229.     // add all the brushes to the main list
  230.     for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
  231.     {
  232.         b->next = active_brushes.next;
  233.         active_brushes.next->prev = b;
  234.         b->prev = &active_brushes;
  235.         active_brushes.next = b;
  236.     }
  237.  
  238.     return ent;
  239. }
  240.  
  241. /*
  242. ============
  243. Entity_Write
  244. ============
  245. */
  246. void Entity_Write (entity_t *e, FILE *f, qboolean use_region)
  247. {
  248.     epair_t        *ep;
  249.     brush_t        *b;
  250.     vec3_t        origin;
  251.     char        text[128];
  252.     int            count;
  253.  
  254.     // if none of the entities brushes are in the region,
  255.     // don't write the entity at all
  256.     if (use_region)
  257.     {
  258.         // in region mode, save the camera position as playerstart
  259.         if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") )
  260.         {
  261.             fprintf (f, "{\n");
  262.             fprintf (f, "\"classname\" \"info_player_start\"\n");
  263.             fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)camera.origin[0],
  264.                 (int)camera.origin[1], (int)camera.origin[2]);
  265.             fprintf (f, "\"angle\" \"%i\"\n", (int)camera.angles[YAW]);
  266.             fprintf (f, "}\n");
  267.             return;
  268.         }
  269.  
  270.         for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  271.             if (!Map_IsBrushFiltered(b))
  272.                 break;    // got one
  273.  
  274.         if (b == &e->brushes)
  275.             return;        // nothing visible
  276.     }
  277.  
  278.     // if fixedsize, calculate a new origin based on the current
  279.     // brush position
  280.     if (e->eclass->fixedsize)
  281.     {
  282.         VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
  283.         sprintf (text, "%i %i %i", (int)origin[0],
  284.             (int)origin[1], (int)origin[2]);
  285.         SetKeyValue (e, "origin", text);
  286.     }
  287.  
  288.     fprintf (f, "{\n");
  289.     for (ep = e->epairs ; ep ; ep=ep->next)
  290.         fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
  291.  
  292.     if (!e->eclass->fixedsize)
  293.     {
  294.         count = 0;
  295.         for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  296.         {
  297.             if (!use_region || !Map_IsBrushFiltered (b))
  298.             {
  299.                 fprintf (f, "// brush %i\n", count);
  300.                 count++;
  301.                 Brush_Write (b, f);
  302.             }
  303.         }
  304.     }
  305.     fprintf (f, "}\n");
  306. }
  307.  
  308.  
  309.  
  310. /*
  311. ============
  312. Entity_Create
  313.  
  314. Creates a new entity out of the selected_brushes list.
  315. If the entity class is fixed size, the brushes are only
  316. used to find a midpoint.  Otherwise, the brushes have
  317. their ownershi[ transfered to the new entity.
  318. ============
  319. */
  320. entity_t    *Entity_Create (eclass_t *c)
  321. {
  322.     entity_t    *e;
  323.     brush_t        *b;
  324.     vec3_t        mins, maxs;
  325.     int            i;
  326.  
  327.     // check to make sure the brushes are ok
  328.  
  329.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  330.         if (b->owner != world_entity)
  331.         {
  332.             Sys_Printf ("Entity NOT created, brushes not all from world\n");
  333.             Sys_Beep ();
  334.             return NULL;
  335.         }
  336.  
  337.     // create it
  338.  
  339.     e = qmalloc(sizeof(*e));
  340.     e->brushes.onext = e->brushes.oprev = &e->brushes;
  341.     e->eclass = c;
  342.     SetKeyValue (e, "classname", c->name);
  343.  
  344.     // add the entity to the entity list
  345.     e->next = entities.next;
  346.     entities.next = e;
  347.     e->next->prev = e;
  348.     e->prev = &entities;
  349.  
  350.     if (c->fixedsize)
  351.     {
  352.         //
  353.         // just use the selection for positioning
  354.         //
  355.         b = selected_brushes.next;
  356.         for (i=0 ; i<3 ; i++)
  357.             e->origin[i] = b->mins[i] - c->mins[i];
  358.  
  359.         // create a custom brush
  360.         VectorAdd (c->mins, e->origin, mins);
  361.         VectorAdd (c->maxs, e->origin, maxs);
  362.         b = Brush_Create (mins, maxs, &c->texdef);
  363.  
  364.         Entity_LinkBrush (e, b);
  365.  
  366.         // delete the current selection
  367.         Select_Delete ();
  368.  
  369.         // select the new brush
  370.         b->next = b->prev = &selected_brushes;
  371.         selected_brushes.next = selected_brushes.prev = b;
  372.  
  373.         Brush_Build( b );
  374.     }
  375.     else
  376.     {
  377.         //
  378.         // change the selected brushes over to the new entity
  379.         //
  380.         for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  381.         {
  382.             Entity_UnlinkBrush (b);
  383.             Entity_LinkBrush (e, b);
  384.             Brush_Build( b );    // so the key brush gets a name
  385.         }
  386.     }
  387.  
  388.     Sys_UpdateWindows (W_ALL);
  389.     return e;
  390. }
  391.  
  392.  
  393. /*
  394. ===========
  395. Entity_LinkBrush
  396. ===========
  397. */
  398. void Entity_LinkBrush (entity_t *e, brush_t *b)
  399. {
  400.     if (b->oprev || b->onext)
  401.         Error ("Entity_LinkBrush: Allready linked");
  402.     b->owner = e;
  403.  
  404.     b->onext = e->brushes.onext;
  405.     b->oprev = &e->brushes;
  406.     e->brushes.onext->oprev = b;
  407.     e->brushes.onext = b;
  408. }
  409.  
  410. /*
  411. ===========
  412. Entity_UnlinkBrush
  413. ===========
  414. */
  415. void Entity_UnlinkBrush (brush_t *b)
  416. {
  417.     if (!b->owner || !b->onext || !b->oprev)
  418.         Error ("Entity_UnlinkBrush: Not currently linked");
  419.     b->onext->oprev = b->oprev;
  420.     b->oprev->onext = b->onext;
  421.     b->onext = b->oprev = NULL;
  422.     b->owner = NULL;
  423. }
  424.  
  425.  
  426.  
  427. /*
  428. ===========
  429. Entity_Clone
  430. ===========
  431. */
  432. entity_t    *Entity_Clone (entity_t *e)
  433. {
  434.     entity_t    *n;
  435.     epair_t        *ep, *np;
  436.  
  437.     n = qmalloc(sizeof(*n));
  438.     n->brushes.onext = n->brushes.oprev = &n->brushes;
  439.     n->eclass = e->eclass;
  440.  
  441.     // add the entity to the entity list
  442.     n->next = entities.next;
  443.     entities.next = n;
  444.     n->next->prev = n;
  445.     n->prev = &entities;
  446.  
  447.     for (ep = e->epairs ; ep ; ep=ep->next)
  448.     {
  449.         np = qmalloc(sizeof(*np));
  450.         np->key = copystring(ep->key);
  451.         np->value = copystring(ep->value);
  452.         np->next = n->epairs;
  453.         n->epairs = np;
  454.     }
  455.     return n;
  456. }
  457.  
  458. int GetUniqueTargetId(int iHint)
  459. {
  460.     int iMin, iMax, i;
  461.     BOOL fFound;
  462.     entity_t *pe;
  463.     
  464.     fFound = FALSE;
  465.     pe = entities.next;
  466.     iMin = 0; 
  467.     iMax = 0;
  468.     
  469.     for (; pe != NULL && pe != &entities ; pe = pe->next)
  470.     {
  471.         i = IntForKey(pe, "target");
  472.         if (i)
  473.         {
  474.             iMin = min(i, iMin);
  475.             iMax = max(i, iMax);
  476.             if (i == iHint)
  477.                 fFound = TRUE;
  478.         }
  479.     }
  480.  
  481.     if (fFound)
  482.         return iMax + 1;
  483.     else
  484.         return iHint;
  485. }
  486.  
  487. entity_t *FindEntity(char *pszKey, char *pszValue)
  488. {
  489.     entity_t *pe;
  490.     
  491.     pe = entities.next;
  492.     
  493.     for (; pe != NULL && pe != &entities ; pe = pe->next)
  494.     {
  495.         if (!strcmp(ValueForKey(pe, pszKey), pszValue))
  496.             return pe;
  497.     }
  498.  
  499.     return NULL;
  500. }
  501.  
  502. entity_t *FindEntityInt(char *pszKey, int iValue)
  503. {
  504.     entity_t *pe;
  505.     
  506.     pe = entities.next;
  507.     
  508.     for (; pe != NULL && pe != &entities ; pe = pe->next)
  509.     {
  510.         if (IntForKey(pe, pszKey) == iValue)
  511.             return pe;
  512.     }
  513.  
  514.     return NULL;
  515. }
  516.  
  517.